﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TomanuExtensions;
using RaytracerLib.MathLib;
using RaytracerLib;

namespace Raytracer.Generator
{
    public class PolynomialSurfaceInfo
    {
        public string Equation = "";
        public bool Closed = true;
        public string Parameter1 = "";
        public string Parameter2 = "";
        public string Parameter3 = "";
        public Vector3 Scale = Vector3.ONE;
        public string Name;
        public AABB LocalBoundBox = new AABB(Vector3.MINIMUM, Vector3.MAXIMUM);
    }

    public static class PolynomialSurfaces
    {
        public readonly static List<PolynomialSurfaceInfo> List;

        static PolynomialSurfaces()
        {
            List = new List<PolynomialSurfaceInfo>()
            {
                new PolynomialSurfaceInfo()
                {
                    Equation = "z^2x^2-z^4-2zx^2+2z^3+x^2-z^2-(x^2-z)^2-(y*1.26)^4-2x^2(y*1.26)^2-(y*1.26)^2z^2+2(y*1.26)^2z+(y*1.26)^2",
                    Name = "Cushion", 
                    Scale = new Vector3(1, 1.26, 1) * 1.5, 
                    LocalBoundBox = new AABB(new Vector3(-1, -1, -1), new Vector3(1, 1, 1))
                }, 

                new PolynomialSurfaceInfo()
                {
                    Equation = "4z^4+(x^2+y^2-4z^2)",
                    Name = "Eight", 
                    Scale = Vector3.ONE * 1.5, 
                    LocalBoundBox = new AABB(new Vector3(-1, -1, -1), new Vector3(1, 1, 1))
                }, 

                new PolynomialSurfaceInfo()
                {
                    Equation = "((x*1.14)^2+9/4(y*0.68)^2+(z*1.24)^2-1)^3-(x*1.14)^2(z*1.24)^3-9/(80)(y*0.68)^2(z*1.24)^3",
                    Name = "Heart 1",
                    Scale = new Vector3(1.14, 0.68, 1.24) * 1.5, 
                    LocalBoundBox = new AABB(new Vector3(-1, -1, -1), new Vector3(1, 1, 1))
                }, 

                new PolynomialSurfaceInfo()
                {
                    Equation = "(2(x*0.72)^2+2(y*0.77)^2+(z*1.16)^2-1)^3-0.1(x*0.72)^2(z*1.16)^3-(y*0.77)^2(z*1.16)^3", 
                    Name = "Heart 2", 
                    Scale = new Vector3(0.72, 0.77, 1.16) * 2, 
                    LocalBoundBox = new AABB(new Vector3(-1, -1, -1), new Vector3(1, 1, 1))
                }, 

                new PolynomialSurfaceInfo()
                {
                    Equation = "4((x*3.1)^2+(y*3.6)^2+(z*2)^2-13)^3+27(3(x*3.1)^2+(y*3.6)^2-4(z*2)^2-12)^2",
                    Name = "Hunt", 
                    Scale = new Vector3(3.1, 3.6, 2) * 0.6,
                    LocalBoundBox = new AABB(new Vector3(-1, -1, -1), new Vector3(1, 1, 1))
                }, 

                new PolynomialSurfaceInfo()
                {
                    Equation = "0.5^4((x/2)^2+(z/2)^2)+((y/2)-0.5)^3((y/2)+0.5)^3",
                    Name = "Lemon", 
                    Scale = Vector3.ONE * 2, 
                    LocalBoundBox = new AABB(new Vector3(-1, -1, -1), new Vector3(1, 1, 1))
                }, 

                new PolynomialSurfaceInfo()
                {
                    Equation = "(((x*0.5)+0.5)^4-((x*0.5)+0.5)^3)+((y*0.34)^2+(z*0.34)^2)", 
                    Name = "Piriform", 
                    Scale = new Vector3(0.5, 0.34, 0.34) * 4, 
                    LocalBoundBox = new AABB(new Vector3(-1, -1, -1), new Vector3(1, 1, 1))
                }, 

                new PolynomialSurfaceInfo()
                {
                    Equation = "(x^2+y^2+z^2-1)^2=((z-1)^2-2x^2)((z+1)^2-2y^2)",
                    Name = "Roman 1", 
                    Scale = Vector3.ONE * 2, 
                    LocalBoundBox = new AABB(new Vector3(-1, -1, -1), new Vector3(1, 1, 1))
                }, 

                new PolynomialSurfaceInfo()
                {
                    Equation = "x^2y^2+x^2z^2+y^2z^2+2xyz",
                    Name = "Roman 2", 
                    Scale = Vector3.ONE * 2, 
                    LocalBoundBox = new AABB(new Vector3(-1, -1, -1), new Vector3(1, 1, 1))
                }, 

                new PolynomialSurfaceInfo()
                {
                    Equation = "4x^2y^2z^2+(x-y-z)(x+y-z)(x-y+z)(x+y+z)",
                    Name = "Sine", 
                    LocalBoundBox = new AABB(new Vector3(-1, -1, -1), new Vector3(1, 1, 1))
                }, 

                new PolynomialSurfaceInfo()
                {
                    Equation = "(x*1.2)^4+(y*1.2)^4+(z*1.2)^4-((x*1.2)^2+(y*1.2)^2+(z*1.2)^2)",
                    Name = "Tooth", 
                    Scale = new Vector3(1.2, 1.2, 1.2) * 1, 
                    LocalBoundBox = new AABB(new Vector3(-1, -1, -1), new Vector3(1, 1, 1))
                }, 

                new PolynomialSurfaceInfo()
                {
                    Equation = "((x*(R+r))^2+(y*r)^2+(z*(R+r))^2+R^2-r^2)^2-4R^2((x*(R+r))^2+(z*(R+r))^2)",
                    Name = "Torus", 
                    Parameter1 = "R=1.1", 
                    Parameter2 = "r=0.6", 
                    Scale = new Vector3(1.1+0.6, 0.6, 1.1+0.6), 
                    LocalBoundBox = new AABB(new Vector3(-1, -1, -1), new Vector3(1, 1, 1))
                }, 

                new PolynomialSurfaceInfo()
                {
                    Equation = "x^2+y^2+z^2-1",
                    Name = "Sphere", 
                    LocalBoundBox = new AABB(new Vector3(-1, -1, -1), new Vector3(1, 1, 1))
                }, 

                new PolynomialSurfaceInfo()
                {
                    Equation = "x^2+y^2-z",
                    Name = "Paraboloid", 
                    Closed = false, 
                    LocalBoundBox = new AABB(new Vector3(Constants.DOUBLE_MIN, 0, Constants.DOUBLE_MIN), 
                        new Vector3(Constants.DOUBLE_MAX, Constants.DOUBLE_MAX, Constants.DOUBLE_MAX))
                }, 

                new PolynomialSurfaceInfo()
                {
                    Equation = "x^2-y^2-z",
                    Name = "Hyperbolic paraboloid", 
                    Closed = false
                }, 

                new PolynomialSurfaceInfo()
                {
                    Equation = "x^2+y^2-z^2-1",
                    Name = "Hyperboloid 1",
                    Closed = false
                }, 

                new PolynomialSurfaceInfo()
                {
                    Equation = "x^2+y^2-z^2+1",
                    Name = "Hyperboloid 2", 
                    Closed = false
                }, 

                new PolynomialSurfaceInfo()
                {
                    Equation = "x^2+y^2-z^2",
                    Name = "Cone", 
                    Closed = false
                }, 

                new PolynomialSurfaceInfo()
                {
                    Equation = "x^2+y^2-1",
                    Name = "Cylinder", 
                    Closed = false, 
                    LocalBoundBox = new AABB(new Vector3(-1, -1, Constants.DOUBLE_MIN), 
                        new Vector3(1, 1, Constants.DOUBLE_MAX))
                }, 

                new PolynomialSurfaceInfo()
                {
                    Equation = "y^2-z^2-1",
                    Name = "Hyperbolic cylinder", 
                    Closed = false
                }
            }; 

            List = List.OrderBy(el => el.Name).ToList();
        }

        public static PolynomialSurfaceInfo Get(string a_name)
        {
            return List.First(el => el.Name == a_name);
        }
    }
}
